package com.yougong.api.util;


import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;


/**
 * @author muchen
 * @description
 * @date 2021/7/19
 * @since 1.0.0
 **/
@Slf4j
public class AliossUtils {

    private final static String END_POINT = "http://oss-cn-hangzhou.aliyuncs.com";
    private final static String ACCESS_KEY_ID = "LTAI5tFvcjPBfgzdegaKQPP8";
    private final static String ACCESS_KEY_SECRET = "qQ0HQR9Vkb0lxJ9f3tc9RH9Bn3hnTg";


    /**
     * 简单上传文件
     *
     * @param fileDomain 文件域名
     * @param bucketName bucket名称
     * @param key        文件key
     * @param files      文件list
     * @return
     */
    public static List<String> uploadMultipartFile(String fileDomain, String bucketName, String key, List<MultipartFile> files) {

        List<String> resultList = new ArrayList<>();

        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

        if (CollectionUtils.isNotEmpty(files)) {
            for (MultipartFile file : files) {
                try {
                    int i = file.getOriginalFilename().lastIndexOf(".");

                    String suffix = file.getOriginalFilename().substring(i);

                    String fileKey = generateFileKey(suffix, key);

                    ossClient.putObject(bucketName, fileKey, file.getInputStream());

                    resultList.add(fileDomain + "/" + fileKey);
                } catch (Exception e) {
                    log.error("上传失败，文件名：" + file.getOriginalFilename(), e);
                }
            }
        }

        // 关闭OSSClient。
        ossClient.shutdown();
        return resultList;
    }

    /**
     * 简单上传文件
     *
     * @param fileDomain 文件域名
     * @param bucketName bucket名称
     * @param path       文件上传路径
     * @param files      文件list
     * @return
     */
    public static List<String> uploadfiles(String fileDomain, String bucketName, String path, List<MultipartFile> files) {

        List<String> resultList = new ArrayList<>();

        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

        if (CollectionUtils.isNotEmpty(files)) {
            for (MultipartFile file : files) {
                try {
                    //String suffix = file.getOriginalFilename().substring(i);
                    String filePathName = DateUtils.dateToString(new Date(), DateUtils.MSEC_FORMAT) + RandomStringUtils.randomNumeric(2) + "/" + file.getOriginalFilename();

                    String fileKey = path + "/" + filePathName;

                    ossClient.putObject(bucketName, fileKey, file.getInputStream());

                    resultList.add(fileDomain + "/" + fileKey);
                } catch (Exception e) {
                    log.error("上传失败，文件名：" + file.getOriginalFilename(), e);
                }
            }
        }

        // 关闭OSSClient。
        ossClient.shutdown();
        return resultList;
    }

    /**
     * 简单上传文件
     *
     * @param fileDomain 文件域名
     * @param bucketName bucket名称
     * @param path       文件上传路径
     * @param file       文件
     * @return
     */
    public static String uploadfilesByName(String fileDomain, String bucketName, String path, MultipartFile file, String fileName) {

        String resultList = "";
        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        try {
            //String suffix = file.getOriginalFilename().substring(i);
            String filePathName = DateUtils.dateToString(new Date(), DateUtils.MSEC_FORMAT) + RandomStringUtils.randomNumeric(2) + "/" + fileName;

            String fileKey = path + "/" + filePathName;
            ossClient.putObject(bucketName, fileKey, file.getInputStream());

            resultList = "https://" + fileDomain + "/" + fileKey;
        } catch (Exception e) {
            log.error("上传失败，文件名：" + fileName, e);
        }
        // 关闭OSSClient。
        ossClient.shutdown();
        return resultList;
    }


    /**
     * 流上传
     * @param fileDomain
     * @param bucketName
     * @param path
     * @param inputStream
     * @param fileName
     * @return
     */
    public static String uploadfilesByInputStream(String fileDomain, String bucketName, String path,InputStream inputStream , String fileName) {

        String resultList = "";
        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        try {
            //String suffix = file.getOriginalFilename().substring(i);
            String filePathName = DateUtils.dateToString(new Date(), DateUtils.MSEC_FORMAT) + RandomStringUtils.randomNumeric(2) + "/" + fileName;

            String fileKey = path + "/" + filePathName;
            ossClient.putObject(bucketName, fileKey, inputStream);

            resultList = "https://" + fileDomain + "/" + fileKey;
        } catch (Exception e) {
            log.error("上传失败，文件名：" + fileName, e);
        }
        // 关闭OSSClient。
        ossClient.shutdown();
        return resultList;
    }

    /**
     * 简单单个上传
     *
     * @param fileDomain 文件域名
     * @param bucketName bucket名称
     * @param key        文件key
     * @return
     */
    public static String uploadByteArray(String fileDomain, String bucketName, String key, String content) {

        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

        // 上传Byte数组。
        byte[] b = content.getBytes();
        ossClient.putObject(bucketName, key, new ByteArrayInputStream(b));
        // 关闭OSSClient。
        ossClient.shutdown();

        return fileDomain + "/" + key;
    }

    /**
     * 简单上传文件
     *
     * @param fileDomain 文件域名
     * @param bucketName bucket名称
     * @param key        文件key
     * @param files      文件list
     * @return
     */
    public static List<String> uploadFile(String fileDomain, String bucketName, String key, List<File> files) {

        List<String> resultList = new ArrayList<>();

        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

        if (CollectionUtils.isNotEmpty(files)) {
            for (File file : files) {
                try {
                    int i = file.getName().lastIndexOf(".");

                    String suffix = file.getName().substring(i);

                    String fileKey = generateFileKey(suffix, key);

                    ossClient.putObject(bucketName, fileKey, file);

                    resultList.add(fileDomain + "/" + fileKey);
                } catch (Exception e) {
                    log.error("上传失败，文件名：" + file.getName(), e);
                }
            }
        }

        // 关闭OSSClient。
        ossClient.shutdown();
        return resultList;
    }

    /**
     * 简单上传文件
     *
     * @param fileDomain 文件域名
     * @param bucketName bucket名称
     * @param path       文件key
     * @param file       文件list
     * @return
     */
    public static String uploadFileByName(String fileDomain, String bucketName, String path, File file, String fileName) { //(String fileDomain,String bucketName,String path,MultipartFile file,String fileName)

        String resultList = "";

        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

        try {
            String filePathName = DateUtils.dateToString(new Date(), DateUtils.MSEC_FORMAT) + RandomStringUtils.randomNumeric(2) + "/" + fileName;

            String fileKey = path + "/" + filePathName;
            ossClient.putObject(bucketName, fileKey, file);

            resultList = fileDomain + "/" + fileKey;

        } catch (Exception e) {
            log.error("上传失败，文件名：" + file.getName(), e);
        }

        // 关闭OSSClient。
        ossClient.shutdown();
        return resultList;
    }


    /**
     * 简单上传文件
     *
     * @param fileDomain 文件域名
     * @param bucketName bucket名称
     * @param path       文件key
     * @param file       文件list
     * @return
     */
    public static String uploadFileByNameWithOutDic(String fileDomain, String bucketName, String path, File file, String fileName) {

        String resultList = "";

        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

        try {
            String fileKey = path + "/" + fileName;
            ossClient.putObject(bucketName, fileKey, file);

            resultList = fileDomain + "/" + fileKey;

        } catch (Exception e) {
            log.error("上传失败，文件名：" + file.getName(), e);
        }

        // 关闭OSSClient。
        ossClient.shutdown();
        return resultList;
    }

    /**
     * 简单上传文件
     *
     * @param fileDomain 文件域名
     * @param bucketName bucket名称
     * @param key        文件key
     * @param files      文件list
     * @return
     */
    public static List<String> uploadFile(String fileDomain, String bucketName, String endPoint, String key, List<File> files) {

        List<String> resultList = new ArrayList<>();

        OSSClient ossClient = new OSSClient(endPoint, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

        if (CollectionUtils.isNotEmpty(files)) {
            for (File file : files) {
                try {
                    int i = file.getName().lastIndexOf(".");

                    String suffix = file.getName().substring(i);

                    String fileKey = generateFileKey(suffix, key);

                    ossClient.putObject(bucketName, fileKey, file);

                    resultList.add(fileDomain + "/" + fileKey);
                } catch (Exception e) {
                    log.error("上传失败，文件名：" + file.getName(), e);
                }
            }
        }

        // 关闭OSSClient。
        ossClient.shutdown();
        return resultList;
    }

    /**
     * 删除
     *
     * @param keys 文件list
     * @return
     */
    public static void batchDelete(String bucketName, List<String> keys) {

//        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
//
//        DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(
//                new DeleteObjectsRequest(bucketName).withKeys(keys));
//
//        List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
//
//        ObjectMapper objectMapper = new ObjectMapper();
//        try {
//            log.info("删除：" + objectMapper.writeValueAsString(deletedObjects));
//        } catch (IOException e) {
//            log.error("系统异常：{0}", e);
//        }
//
//        // 关闭OSSClient。
//        ossClient.shutdown();
    }

    /**
     * 简单上传文件 -- Byte数组
     *
     * @param bucketName bucket名称
     * @param key        文件key
     * @return 文件url
     */
    public static String uploadByByte(String fileDomain, String bucketName, String key, byte[] b) throws Exception {
        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

        // 上传Byte数组。
        ossClient.putObject(bucketName, key, new ByteArrayInputStream(b));
        // 关闭OSSClient。
        ossClient.shutdown();

        return fileDomain + key;
    }

    /**
     * 文件上传 -- 输入流
     *
     * @param key          文件key
     * @param base64String
     * @return
     */
    public static String uploadByBase64(String fileDomain, String bucketName, String key, String base64String) throws IOException {
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] bates = decoder.decodeBuffer(base64String);
        //OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        OSS ossClient = new OSSClientBuilder().build(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

        // 上传Byte数组。
        ossClient.putObject(bucketName, key, new ByteArrayInputStream(bates));
        // 关闭OSSClient。
        ossClient.shutdown();

        return fileDomain + "/" + key;
        //return upload(DOMAIN_BZ, HANGZHOU_ENDPOINT, BUCKET_NAME_BZ, key, bates);
    }

    /**
     * 简单单个上传
     *
     * @param fileDomain 文件域名
     * @param bucketName bucket名称
     * @param key        文件key
     * @return
     */
    public static String uploadFile(String fileDomain, String bucketName, String key, InputStream inputStream) {

        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);

        ossClient.putObject(bucketName, key, inputStream);
        // 关闭OSSClient。
        ossClient.shutdown();

        return fileDomain + "/" + key;
    }

    /**
     * 简单单个上传 强制下载
     *
     * @param fileDomain 文件域名
     * @param bucketName bucket名称
     * @param key        文件key
     * @return
     */
    public static String uploadFileForceDownload(String fileDomain, String bucketName, String key, InputStream inputStream) {

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);


        // <yourObjectName>表示上传文件到OSS时需要指定包含文件后缀在内的完整路径，例如abc/efg/123.jpg。
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, inputStream);

        // 如果需要上传时设置存储类型与访问权限，请参考以下示例代码。
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setHeader(OSSHeaders.CONTENT_DISPOSITION, "attachment;");
//        //header('Content-type: application/pdf');
//        metadata.setHeader(OSSHeaders.CONTENT_TYPE,"application/pdf");

        putObjectRequest.setMetadata(metadata);

        // 上传字符串。
        ossClient.putObject(putObjectRequest);

        // 关闭OSSClient。
        ossClient.shutdown();

        return fileDomain + "/" + key;
    }


    /**
     * @param url
     * @return
     * @Title: getInputStreamByFileUrl
     * @Description: 根据文件路径获取InputStream流
     * @return: InputStream
     */
    public static InputStream getInputStreamByFileUrl(String url) {
        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(OssContants.DEFAULT_BUCKET_NAME, url);
        return ossObject.getObjectContent();
    }


    public static byte[] getFile(String url) throws IOException {
        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject object = ossClient.getObject(OssContants.DEFAULT_BUCKET_NAME, url);
        InputStream in = object.getObjectContent();
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        int ch;
        while ((ch = in.read()) != -1) {
            outStream.write(ch);
        }
        return outStream.toByteArray();
    }

    private static String generateFileKey(String suffix, String key) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String dateStr = sdf.format(new Date());

        String fileName = dateStr + "-" + UUID.randomUUID().toString() + suffix;

        return key + "/001/" + fileName;
    }

    public static byte[] getFile(String bucketName, String key) throws IOException {
        OSSClient ossClient = new OSSClient(END_POINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
        OSSObject object = ossClient.getObject(bucketName, key);
        InputStream in = object.getObjectContent();
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        int ch;
        while ((ch = in.read()) != -1) {
            outStream.write(ch);
        }
        return outStream.toByteArray();
    }

}
